package com.mdd.admin.service.time.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mdd.admin.service.time.IOrderTimeService;
import com.mdd.admin.validate.common.PageParam;
import com.mdd.admin.validate.time.OrderTimeParam;
import com.mdd.admin.validate.time.TimeParam;
import com.mdd.admin.vo.time.OrderTimeDetailVo;
import com.mdd.admin.vo.time.OrderTimeListVo;
import com.mdd.common.constant.GlobalConstant;
import com.mdd.common.core.PageResult;
import com.mdd.common.entity.time.OrderTime;
import com.mdd.common.exception.OperateException;
import com.mdd.common.mapper.time.OrderTimeMapper;
import com.mdd.common.utils.ConfigUtil;
import com.mdd.common.utils.TimeUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.*;

/**
 * 订单预约时间实现类
 */
@Service
public class OrderTimeServiceImpl implements IOrderTimeService {

    @Resource
    OrderTimeMapper orderTimeMapper;

    /**
     * 订单预约时间列表
     *
     * @param pageParam 分页参数
     * @param params    搜索参数
     * @return PageResult<OrderTimeListVo>
     */
    @Override
    public PageResult<OrderTimeListVo> list(PageParam pageParam, Map<String, String> params) {
        Integer page = pageParam.getPageNo();
        Integer limit = pageParam.getPageSize();

        QueryWrapper<OrderTime> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_delete", 0);
        queryWrapper.orderByDesc("sort");

        orderTimeMapper.setSearch(queryWrapper, params, new String[]{
                "datetime:startTimeStart-startTimeEnd@start_time:str",
                "datetime:endTimeStart-endTimeEnd@end_time:str",
                "=:sort:int",
        });

        IPage<OrderTime> iPage = orderTimeMapper.selectPage(new Page<>(page, limit), queryWrapper);

        List<OrderTimeListVo> list = new LinkedList<>();
        for (OrderTime item : iPage.getRecords()) {
            OrderTimeListVo vo = new OrderTimeListVo();
            BeanUtils.copyProperties(item, vo);
            vo.setCreateTime(TimeUtil.timestampToDate(item.getCreateTime()));
            vo.setUpdateTime(TimeUtil.timestampToDate(item.getUpdateTime()));
            vo.setStartTime(item.getStartTime());
            vo.setEndTime(item.getEndTime());
            vo.setTimeDesc(item.getStartTime() + " - " + item.getEndTime());
            list.add(vo);
        }

        return PageResult.iPageHandle(iPage.getTotal(), iPage.getCurrent(), iPage.getSize(), list);
    }

    /**
     * 订单预约时间详情
     *
     * @param id 主键参数
     * @return OrderTime
     */
    @Override
    public OrderTimeDetailVo detail(Long id) {
        OrderTime model = orderTimeMapper.selectOne(
                new QueryWrapper<OrderTime>()
                        .eq("id", id)
                        .last("limit 1"));

        Assert.notNull(model, "数据不存在");
        OrderTimeDetailVo vo = new OrderTimeDetailVo();
        BeanUtils.copyProperties(model, vo);
        vo.setStartTime(model.getStartTime());
        vo.setEndTime(model.getEndTime());
        return vo;
    }

    /**
     * 订单预约时间新增
     *
     * @param orderTimeParam 参数
     */
    @Override
    public void add(OrderTimeParam orderTimeParam) {
        LambdaQueryWrapper<OrderTime> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.ge(OrderTime::getStartTime, orderTimeParam.getStartTime());
        lambdaQueryWrapper.le(OrderTime::getEndTime, orderTimeParam.getEndTime());
        lambdaQueryWrapper.eq(OrderTime::getIsDelete, GlobalConstant.NOT_DELETE);
        lambdaQueryWrapper.last("limit 1");
        OrderTime orderTime = orderTimeMapper.selectOne(lambdaQueryWrapper);
        Assert.isNull(orderTime, "时间段存在重复,请检查预约时间! ");
        if (validateStartAndEnd(orderTimeParam.getStartTime(), orderTimeParam.getEndTime())) {
            throw new OperateException("预约的开始时间应该小于预约的结束时间!");
        }
        OrderTime model = new OrderTime();
        model.setStartTime(orderTimeParam.getStartTime());
        model.setEndTime(orderTimeParam.getEndTime());
        model.setSort(orderTimeParam.getSort());
        model.setCreateTime(TimeUtil.timestamp());
        model.setUpdateTime(TimeUtil.timestamp());
        orderTimeMapper.insert(model);
    }

    private boolean validateStartAndEnd(String startTimeStr, String endTimeStr) {
        Long startTime = Long.valueOf(startTimeStr.replace(":", ""));
        Long endTime = Long.valueOf(endTimeStr.replace(":", ""));
        if (endTime <= startTime) {
            return true;
        }
        return false;
    }

    /**
     * 订单预约时间编辑
     *
     * @param orderTimeParam 参数
     */
    @Override
    public void edit(OrderTimeParam orderTimeParam) {
        OrderTime model = orderTimeMapper.selectOne(
                new QueryWrapper<OrderTime>()
                        .eq("id", orderTimeParam.getId())
                        .last("limit 1"));

        Assert.notNull(model, "数据不存在!");
        model.setId(orderTimeParam.getId());
        model.setSort(orderTimeParam.getSort());
        model.setStartTime(orderTimeParam.getStartTime());
        model.setEndTime(orderTimeParam.getEndTime());
        model.setUpdateTime(TimeUtil.timestamp());
        orderTimeMapper.updateById(model);
    }

    /**
     * 订单预约时间删除
     *
     * @param id 主键ID
     */
    @Override
    public void del(Long id) {
        OrderTime model = orderTimeMapper.selectOne(
                new QueryWrapper<OrderTime>()
                        .eq("id", id)
                        .last("limit 1"));

        Assert.notNull(model, "数据不存在!");
        model.setIsDelete(GlobalConstant.DELETE);
        model.setDeleteTime(TimeUtil.timestamp());
        orderTimeMapper.updateById(model);
    }

    @Override
    public void batchDel(Long[] ids) {
        for (Long id : ids) {
            orderTimeMapper.updateById(new OrderTime()
                            .setId(id)
                            .setIsDelete(GlobalConstant.DELETE)
                            .setDeleteTime(TimeUtil.timestamp()));
        }
    }

    /**
     * @return 订单时间
     */
    @Override
    public Map<String, Object> getOrderTime() {
        Map<String, Object> map = new LinkedHashMap<>();
        Integer time = Integer.valueOf(ConfigUtil.get(GlobalConstant.ORDER_TIME_TYPE, GlobalConstant.ORDER_TIME));
        map.put("time",time);
        LambdaQueryWrapper<OrderTime> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(OrderTime::getIsDelete,0).orderByAsc(OrderTime::getId);
        List<OrderTime> orderTimes = orderTimeMapper.selectList(lambdaQueryWrapper);
        map.put("orderTime",orderTimes);
        return map;
    }

    /**
     * @param timeParam 时间参数
     */
    @Override
    public void setTime(TimeParam timeParam) {
        if (timeParam.getTime() == null || timeParam.getTime() == 0) {
            timeParam.setTime(7);
        } else if (timeParam.getTime() < 0) {
            throw new OperateException("提前预约时长不能为负数");
        }
        ConfigUtil.set(GlobalConstant.ORDER_TIME_TYPE, GlobalConstant.ORDER_TIME, String.valueOf(timeParam.getTime()));
        LambdaQueryWrapper<OrderTime> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.gt(OrderTime::getId,0);
        orderTimeMapper.delete(lambdaQueryWrapper);
        timeParam.getOrderTimeList().forEach(
                item -> {
                    Assert.isTrue(item.getSort() > -1, "排序值不能为负数");
                    OrderTime orderTime = new OrderTime();
                    orderTime.setStartTime(item.getStartTime());
                    orderTime.setEndTime(item.getEndTime());
                    orderTime.setIsDelete(0);
                    orderTime.setSort(item.getSort());
                    orderTime.setCreateTime(System.currentTimeMillis() / 1000);
                    orderTime.setUpdateTime(System.currentTimeMillis() / 1000);
                    orderTimeMapper.insert(orderTime);
                }
        );
    }
}
